/* adt_complex.h
 * A complex (single precision only), bicomplex and quaternion numbers and arithmetic.
 * ADT (Altai Diffraction Team)
 *
 * Copyright (C) 2010 Vsevolod Scherbinin
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifdef ONDEVICE
#define ADTFUNTYPE __device__
#define ADTFUNNAME(fn) adt_cuda_complex_##fn
#else
#define ADTFUNTYPE 
#define ADTFUNNAME(fn) adt_complex_##fn
#endif /* ONDEVICE */

//Unary function for complex type
ADTFUNTYPE adt_complex_float ADTFUNNAME(rect) (float x, float y); //returning complex number x+iy
ADTFUNTYPE adt_complex_float ADTFUNNAME(polar) (float r, float theta); //returning complex number r \cos theta + i r \sin theta

ADTFUNTYPE float ADTFUNNAME(arg) (adt_complex_float z); //This function returns the argument of the complex number z, \arg(z), where -\pi < \arg(z) <= \pi.
ADTFUNTYPE float ADTFUNNAME(abs) (adt_complex_float z); //This function returns the magnitude of the complex number z, |z|.
ADTFUNTYPE float ADTFUNNAME(abs2) (adt_complex_float z); //This function returns the squared magnitude of the complex number z, |z|^2.

//Binary function for complex type
ADTFUNTYPE adt_complex_float ADTFUNNAME(add) (adt_complex_float z1, adt_complex_float z2); //This function returns the sum of the complex numbers a and b, z=a+b.
ADTFUNTYPE adt_complex_float ADTFUNNAME(sub) (adt_complex_float z1, adt_complex_float z2); //This function returns the difference of the complex numbers a and b, z=a-b.
ADTFUNTYPE adt_complex_float ADTFUNNAME(mul) (adt_complex_float z1, adt_complex_float z2); //This function returns the product of the complex numbers a and b, z=ab.
ADTFUNTYPE adt_complex_float ADTFUNNAME(div) (adt_complex_float z1, adt_complex_float z2); //This function returns the quotient of the complex numbers a and b, z=a/b.
ADTFUNTYPE adt_complex_float ADTFUNNAME(add_real) (adt_complex_float z, float x); //This function returns the sum of the complex number z and the real number x, z=a+x.
ADTFUNTYPE adt_complex_float ADTFUNNAME(sub_real) (adt_complex_float z, float x); //This function returns the difference of the complex number z and the real number x, z=a-x.
ADTFUNTYPE adt_complex_float ADTFUNNAME(mul_real) (adt_complex_float z, float x); //This function returns the product of the complex number z and the real number x, z=ax.
ADTFUNTYPE adt_complex_float ADTFUNNAME(div_real) (adt_complex_float z, float x); //This function returns the quotient of the complex number z and the real number x, z=a/x.
ADTFUNTYPE adt_complex_float ADTFUNNAME(add_imag) (adt_complex_float z, float y); //This function returns the sum of the complex number z and the imaginary number iy, z=a+iy.
ADTFUNTYPE adt_complex_float ADTFUNNAME(sub_imag) (adt_complex_float z, float y); //This function returns the difference of the complex number z and the imaginary number iy, z=a-iy.
ADTFUNTYPE adt_complex_float ADTFUNNAME(mul_imag) (adt_complex_float z, float y); //This function returns the product of the complex number z and the imaginary number iy, z=a*(iy).
ADTFUNTYPE adt_complex_float ADTFUNNAME(div_imag) (adt_complex_float z, float y); //This function returns the quotient of the complex number z and the imaginary number iy, z=a/(iy).
ADTFUNTYPE adt_complex_float ADTFUNNAME(conjugate) (adt_complex_float z); //This function returns the complex conjugate of the complex number z, z^* = x - i y.
ADTFUNTYPE adt_complex_float ADTFUNNAME(inverse) (adt_complex_float z); //This function returns the inverse, or reciprocal, of the complex number z, 1/z = (x - i y)/(x^2 + y^2).
ADTFUNTYPE adt_complex_float ADTFUNNAME(negative) (adt_complex_float z); //This function returns the negative of the complex number z, -z = (-x) + i(-y).

//More functions for complex type
ADTFUNTYPE adt_complex_float ADTFUNNAME(sqrt) (adt_complex_float z); //This function returns the square root of the complex number z, \sqrt z. The branch cut is the negative real axis. The result always lies in the right half of the complex plane.
ADTFUNTYPE adt_complex_float ADTFUNNAME(exp) (adt_complex_float z); //This function returns the complex exponential of the complex number z, \exp(z).

//Unary function for bicomplex type
ADTFUNTYPE adt_bicomplex_float ADTFUNNAME(bicomplex_rect) (float x, float y, float u, float v); //returning bicomplex number x+jy+iu+ijv
ADTFUNTYPE adt_bicomplex_float ADTFUNNAME(bicomplex_cmplx) (adt_complex_float z1, adt_complex_float z2); //returning bicomplex number Re(z1)+jIm(z1)+iRe(z2)+ijIm(z2)
ADTFUNTYPE adt_complex_float ADTFUNNAME(bicomplex_real) (adt_bicomplex_float b); //returning the two first components as complex number
ADTFUNTYPE adt_complex_float ADTFUNNAME(bicomplex_imag) (adt_bicomplex_float b); //returning the two last components as complex number

ADTFUNTYPE float ADTFUNNAME(bicomplex_abs) (adt_complex_float z); //This function returns the magnitude of the complex number z, |z|.
ADTFUNTYPE float ADTFUNNAME(bicomplex_abs4) (adt_complex_float z); //This function returns the quadrupled magnitude of the complex number z, |z|^4.

//Binary function for complex type
ADTFUNTYPE adt_bicomplex_float ADTFUNNAME(bicomplex_add) (adt_bicomplex_float b1, adt_bicomplex_float b2); //This function returns the sum of the bicomplex numbers b1 and b2, b=b1+b2.
ADTFUNTYPE adt_bicomplex_float ADTFUNNAME(bicomplex_sub) (adt_bicomplex_float b1, adt_bicomplex_float b2); //This function returns the difference of the bicomplex numbers b1 and b2, b=b1-b2.
ADTFUNTYPE adt_bicomplex_float ADTFUNNAME(bicomplex_mul) (adt_bicomplex_float b1, adt_bicomplex_float b2); //This function returns the product of the bicomplex numbers b1 and b2, b=b1b2.

ADTFUNTYPE adt_bicomplex_float ADTFUNNAME(bicomplex_mul_real) (adt_bicomplex_float b, float x); //This function returns the product of the bicomplex number b and the real number x, w=bx.
ADTFUNTYPE adt_bicomplex_float ADTFUNNAME(bicomplex_div_real) (adt_bicomplex_float b, float x); //This function returns the quotient of the bicomplex number b and the real number x, w=b/x.


#undef ADTFUNNAME
#undef ADTFUNTYPE 